// demo/measuring/measuring.js
const { QNMPPlugin, QNConsts } = requirePlugin('QNBleApi');
import getReports from '@yolanda-qn/four-electrodes-report-lib-pe';
import { Report } from '../../report/index';
import { sealGenderParam, formatDate } from '../../util/util';

// wxb0989a4bbce13d87为测试用appid, 记得切换为客户自己的
const APPID = 'wxb0989a4bbce13d87';

/**
 * 微信的本地日志功能，需要用户手动反馈才能拿到日志文件
 */
const logger = () => {
  const wxlogger =
    wx.getLogManager &&
    wx.getLogManager({
      level: 0,
    });
  const log = (...params) => {
    console.log(...params);
    wxlogger && wxlogger.log(...params);
  };
  return {
    log,
  };
};

Page({
  data: {
    age: 30,
    // 1 男 0 女
    gender: 1,
    height: 170,
    unit: 'kg',
    realTimeWeight: 0,
    bleState: '空闲',
    state: 'paused',
    measureData: null,
    eightMeasureData: null,
    score: 0,
    // 蓝牙是否可用
    available: false,
    // 发现设备中
    discovering: false,
    // 是否已连接
    connected: false,
    // 是否正在连接
    connecting: false,
    // 八电级秤拟合阻抗(仅八电级需要)
    hmac: '',
  },

  onLoad: function (options) {
    console.log('options', options);
    if (options.form) {
      const form = JSON.parse(options.form);
      this.setData({
        ...form,
      });
    }

    /**
     * 判断相关权限是否开启, 根据需求放在合适的位置
     * locationEnabled 是否开启定位
     * locationAuthorized 是否授权定位(仅安卓需要,需要选择始终允许,不能选择询问,因为微信不会询问用户是否开启定位)
     * bluetoothEnabled 蓝牙是否开启
     */
    // const { locationAuthorized, locationEnabled, bluetoothEnabled } = wx.getSystemInfoSync();
    // if (!locationAuthorized || !locationEnabled || !bluetoothEnabled) {
    //   this.tip('请确认相关权限是否开启');
    //   setTimeout(() => {
    //     wx.navigateBack();
    //   }, 2000);
    // }

    // 初始化蓝牙
    this.bleApi = new QNMPPlugin({
      appId: APPID, // 必须, 客户小程序的appid, 需要配置才能使用，
      mpwx: wx, // 非必须 连接广播称时需要
      logger: logger(), // 非必须，日志功能，最好有，方便排查问题，可以替换为客户自己的
    });

    // 错误监听
    this.bleApi.onError = (err) => {
      console.error('捕捉到错误', err.detail);
    };

    // 初始化回调
    this.bleApi.onReady = ({
      bleEnableState, //表示当前蓝牙是否为开启状态
    }) => {
      if (bleEnableState) {
        this.bleApi.startBleDeviceDiscovery(); 
      } else {
        console.log('蓝牙状态为关闭');
      }
    };

    // 设置蓝牙监听事件
    this.bleApi.setBleEventListener(this.bleEventListener());

    // 初始化
    this.bleApi.init();
  },

  onReady: function () {},

  onShow: function () {
    // this.mockNormalScaleData();
    // this.mockEightScaleData();
  },

  onHide: function () {},

  onUnload: function () {
    this.stopBle();
  },
  
  /**
   *  模拟普通数据
   */

  mockNormalScaleData() {
    const scaleData = {
      user: {
        birthday: '1999-1-1',
        gender: 1,
        height: 170,
      },
      device: {
        type: QNConsts.QNBleDeviceType.NORMAL_BLE_SCALE,
      },
      bestVisualWeight: 63,
      bmi: 27.4,
      bmr: 1608,
      bodyAge: 33,
      bodyShape: 6,
      bodyfat: 27.6,
      bodyfatMass: 21.85,
      bone: 2.9,
      fatControl: -9.97,
      fattyLiver: 2,
      heartIndex: 3,
      heartRate: 84,
      lbm: 57.3,
      mineralSalt: 1,
      muscleMass: 54.7,
      muscle: 46.8,
      obesity: 25.63,
      protein: 16.5,
      proteinMass: 13.06,
      score: 72.2,
      sinewControl: 3.32,
      sinewRate: 68.86,
      standardWeight: 63,
      subfat: 24.4,
      time: new Date().getTime(),
      visfat: 8,
      stature: 165,
      water: 52.8,
      waterMass: 41.4,
      weight: 75,
      weightControl: -6.65,
    };

    this.analysisData(scaleData);
  },

  /**
   *  模拟8电级数据
   */
  mockEightScaleData() {
    const scaleData = {
      bmi: 26,
      bmr: 1537,
      bodyAge: 34,
      bodyShape: 1,
      bodyfat: 28.1,
      bone: 3.65,
      fatLf: 4.5,
      fatLh: 1.8,
      fatRf: 4.5,
      fatRh: 1.8,
      fatT: 1.8,
      lbm: 54.1,
      muscleMass: 54.7,
      muscle: 38.9,
      muscleLf: 8.7,
      muscleLh: 2.6,
      muscleRf: 8.8,
      muscleRh: 2.7,
      muscleT: 23.2,
      protein: 14.2,
      score: 69.1,
      subfat: 25.4,
      time: new Date().getTime(),
      user: {
        birthday: '2000-1-1',
        gender: 1,
        height: 170,
      },
      device: {
        type: QNConsts.QNBleDeviceType.WSP_EIGHT_DUAL_MODE_SCALE,
      },
      visfat: 8,
      water: 52.8,
      weight: 75.2,
    };
    this.analysisData(scaleData);
  },

  /**
   * 停止蓝牙活动
   */
  stopBle: async function () {
    await this.bleApi.stop();
    await this.bleApi.releaseBleSource();
  },

  /**
   * 刷新蓝牙
   */
  restart() {
    this.bleApi
      .stop()
      .then(() => {
        this.setData({
          connected: false,
        });
        this.bleApi.startBleDeviceDiscovery();
      })
      .catch((err) => {
        console.log('停止扫描失败', err);
      });
  },

  async handlerConnect(device) {
    const { height, gender, age, unit, connected, hmac } = this.data;
    if (this.connecting || connected) {
      console.log('当前正在连接，不再处理');
      return;
    }
    this.connecting = true;
    const birthday = new Date();
    birthday.setFullYear(birthday.getFullYear() - age);
    const user = {
      height,
      gender: sealGenderParam(gender),
      birthday: formatDate(birthday),
    };

    /**
     * 调用连接成功后，会返回本次连接的设备访问对象，可以对设备进行一些蓝牙数据通讯
     * 每次连接返回的都不一样，连接成功后，该对象开始可以操作，连接失败或断开后，该对象会失效
     */
    console.log('要连接的对象', device);
    this.deviceHandler = await this.bleApi.createBleConnection(device, this.deviceEventListener(), {
      user,
      unit,
      hmac,
    });

    console.log('设备方位对象为：', this.deviceHandler);
  },

  // 蓝牙相关事件回调
  bleEventListener() {
    /**
     * 监听扫描到设备的回调
     */
    const onBleDeviceFound = (device) => {
      this.handlerConnect(device);
    };

    /**
     * 监听蓝牙断开连接的回调
     */
    const onDisconnected = (device) => {
      this.updateState('设备连接已断开');
      this.setData({
        connected: false,
        state: 'paused',
        connecting: false,
      });
      this.connecting = false;
      this.connected = false;
      console.log('设备连接已断开', device);
    };

    /**
     * 监听蓝牙状态发生变化回调，连接成功或断开连接都会出触发
     */
    const onBluetoothEnableChange = ({ available }) => {
      if (available) {
        this.updateState('蓝牙可用，空闲');
        this.bleApi.startBleDeviceDiscovery();
      } else {
        this.updateState('蓝牙不可用');
      }
      this.setData({
        available,
      });
    };

    /**
     * 	监听设备连接成功回调
     */
    const onConnected = (device) => {
      this.updateState('已连接');
      console.log('设备已连接', device);
      this.connecting = false;
      this.setData({
        connected: true,
        state: 'running',
        device,
      });
    };

    /**
     * 监听停止扫描的回调
     */
    const onStopDiscoveryDevice = () => {
      this.updateState('已停止扫描');
      this.setData({
        discovering: false,
      });
    };

    /**
     * 监听开始扫描设备的回调
     */
    const onStartDiscoveryDevice = () => {
      this.updateState('开始扫描');
      this.setData({
        devices: [],
        discovering: true,
      });
    };

    return {
      onBleDeviceFound,
      onDisconnected,
      onBluetoothEnableChange,
      onConnected,
      onStopDiscoveryDevice,
      onStartDiscoveryDevice,
    };
  },

  // 秤端相关事件回调
  deviceEventListener() {
    /**
     * 实时测量体重
     */
    const onGetUnsteadyWeight = ({ weight }) => {
      this.updateState('测量中');
      this.setData({
        realTimeWeight: weight,
        state: 'running',
        unit: 'kg',
      });
    };
    /**
     * 获取到了实时的稳定测量数据，在连接APP的情况下，进行测量，数据会进入到这个回调
     * @param {object} measure 体脂秤测量数据
     */
    const onGetScaleData = ({ measure }) => {
      this.updateState('测量完成');
      console.log('测量结束', measure);
      this.analysisData(measure);
    };

    /**
     * 身高秤测量实时身高的回调
     */
    const onGetUnsteadyHeight = ({ height }) => {
      if (height <= 0) return;
      this.setData({
        realTimeHeight: height,
        state: 'running',
        unit: 'cm',
      });
    };

    /**
     * 身高秤测量身高结束的回调
     */
    const onMeasureHeightEnd = ({ weight, height }) => {
      this.setData({
        realTimeWeight: weight,
        realTimeHeight: height,
        state: 'running',
        unit: 'cm',
      });
    };
    /**
     * 请求算法接口错误回调，一般是因为用户信息的参数错误导致
     */
    const onFetchScaleDataFail = (err) => {
      console.error('请求算法接口出错了', err);
    };

    return {
      onGetUnsteadyWeight,
      onGetScaleData,
      onGetUnsteadyHeight,
      onMeasureHeightEnd,
      onMeasureHeightEnd,
      onFetchScaleDataFail,
    };
  },

  /**
   * 处理测量后的数据, 根据设备类型调用不同的处理方法
   */
  analysisData(scaleData) {
    switch (scaleData.device.type) {
      case QNConsts.QNBleDeviceType.WSP_EIGHT_DUAL_MODE_SCALE:
      case QNConsts.QNBleDeviceType.SINGLE_BLE_EIGHT_SCALE:
        this.analysisEightData(scaleData);
        break;
      default:
        this.analysisNormalData(scaleData);
        break;
    }
  },

  /**
   * 展示普通秤测量后的数据，仅供参考，
   */
  analysisNormalData(scaleData) {
    // 配置信息
    const config = {
      weightUnit : 'kg', // 重量单位
      lang : 'zh_CN', // 当前系统语言
    };
    const measureData = {
      ...scaleData.user,
      ...scaleData,
    }
    console.log('构造前', measureData);
    // 这里只是拿到kg数据，尚未进行单位转换和小数位精度fixed处理
    const reports = getReports(measureData, config)
      // 可以使用order字段来排序
      .sort((a, b) => a.order - b.order)
      // toObject会进行单位转换和小数位精度处理，返回的是string类型，不应该使用这里的数据来进行额外计算
      .map((item) => item.toObject());

    this.setData({
      realTimeWeight: 0,
      realTimeHeight: 0,
      state: 'paused',
      score: scaleData.score,
      measureData: reports,
    });
  },

  /**
   * @brief 展示八电级秤测量后的数据，仅供参考，
   *
   */
  analysisEightData(scaleData) {
    // 八电级测出电阻才能显示深度报告
    if (!this.isValidEightMeasure(scaleData)) {
      this.tip('未测出电阻, 请重新测量');
      return;
    }

    // 记录阻抗
    if (scaleData.hmac) {
      // 需要客户自己记录该参数对应的用户
      this.setData({
        hmac: scaleData.hmac,
      });
    }

    this.setData({
      eightMeasureData: scaleData,
      realTimeWeight: 0,
      realTimeHeight: 0,
      state: 'paused',
      score: scaleData.score,
    });
  },

  /**
   * 设置蓝牙提示
   * @param {string} bleState
   * 蓝牙提示信息
   */
  updateState(bleState) {
    this.setData({ bleState });
  },

  /**
   * 提示
   * @param {string} title
   */
  tip(title) {
    wx.showToast({
      icon: 'none',
      title,
      duration: 2500,
    });
  },

  /**
   * 是否是有效的八电级测量数据(是否测出电阻)
   */
  isValidEightMeasure(scaleData) {
    const validKeys = [
      'muscleRh',
      'muscleLh',
      'muscleRf',
      'muscleLf',
      'muscleT',
      'fatRh',
      'fatLh',
      'fatRf',
      'fatLf',
      'fatT',
    ];
    return validKeys.every((key) => scaleData[key])
  },
});
